﻿using System;
using System.Threading;

namespace smp.RabbitMq.Strategies
{
    public class ThreadSleepRetryResponderStrategy : IResponderStrategy
    {
        private readonly int _maxAttempts;
        private readonly int _retrySleepInMilliSeconds;

        public ThreadSleepRetryResponderStrategy()
        {
            _maxAttempts = 3;
            _retrySleepInMilliSeconds = 300000;
        }

        public ThreadSleepRetryResponderStrategy(int maxAttempts)
        {
            _maxAttempts = maxAttempts;
            _retrySleepInMilliSeconds = 300000;
        }

        public ThreadSleepRetryResponderStrategy(int maxRetryAttempts, int retrySleepInMilliSeconds)
        {
            _maxAttempts = maxRetryAttempts;
            _retrySleepInMilliSeconds = retrySleepInMilliSeconds;
        }

        #region Implementation of IResponderStrategy

        public object HandleResponse(IResponderHandler handler, Envelope envelope)
        {
            int attempt = 0;
            while(attempt <= _maxAttempts)
            {
                try
                {
                    var responderHandler = (dynamic)handler;
                    var messageEntity = (dynamic)envelope.Message;
                    InstancesFactory.Log.Debug("Executing responder handler : {0}", handler.GetType());
                    return responderHandler.Respond(messageEntity);
                }
                catch (Exception ex)
                {
                    Thread.Sleep(_retrySleepInMilliSeconds);
                    attempt++;
                    if(attempt >= _maxAttempts)
                    {
                        InstancesFactory.Log.Error(ex, "Handler {0} threw exception while trying to execute for message {1}", handler.GetType(), envelope.Message);
                    }
                    else
                    {
                        InstancesFactory.Log.Warning(ex, "Handler {0} threw exception while trying to execute for message {1}", handler.GetType(), envelope.Message);
                    }
                }
            }
            return null;
        }

        #endregion
    }
}
